package com.quectel.cms.controller.datav;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdcardUtil;
import com.quectel.cms.controller.BaseController;
import com.quectel.core.module.device.dto.datav.DeviceCountDto;
import com.quectel.core.module.device.service.DeviceService;
import com.quectel.core.module.household.dto.HouseholdDto;
import com.quectel.core.module.household.dto.datav.HouseholdCountDto;
import com.quectel.core.module.household.service.HouseholdService;
import com.quectel.core.module.workorder.dto.datav.WorkOrderCountDto;
import com.quectel.core.module.workorder.service.WorkOrderService;
import com.quectel.util.common.DateUtils;
import com.quectel.util.common.Request;
import com.quectel.util.common.Response;
import com.quectel.util.kit.PageFetchKit;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author caolu
 * @email louis.cao@quectel.com
 * @date 2019-05-31 12:10:19
 */
@RestController
@RequestMapping("datav/index")
@Tag(name = "DataVIndexController", description = "大屏首页相关接口")
public class DataVIndexController extends BaseController {

    @DubboReference
    private HouseholdService householdService;

    @DubboReference
    private DeviceService deviceService;

    @DubboReference
    private WorkOrderService workOrderService;

    @GetMapping("countHousehold")
    @Operation(summary = "人口信息统计")
    public Response<HouseholdCountDto> countHousehold(
            @Parameter(description = "小区id 非必填") @RequestParam(required = false) Long villageId
    ) {
        final Date currentDate = new Date();

        Map<String, Object> params = Request.parseParams(httpServletRequest);
        super.fillAuthorityData(params);

        HouseholdCountDto householdCountDto = householdService.countHousehold(params);

        List<HouseholdDto> householdDtos = PageFetchKit.fetchAll(r -> householdService.queryList(r), params);
        // 分段数组
        final int[] segmentArr = new int[]{6, 17, 40, 55, 65};

        // 统计各个年龄段的人数，存储在 map 里，map 的key 为年龄段类型 value 为人数个数
        Map<Byte, Integer> cMap = householdDtos.parallelStream().collect(Collectors.groupingBy(o -> {
            if (StringUtils.isBlank(o.getCardNo()) || !IdcardUtil.isValidCard(o.getCardNo())) {
                return HouseholdCountDto.SegmentEnum.UNKNOWN.getType();
            }
            try {
                Date parse = DateUtils.parse(o.getCardNo().substring(6, 14), DateUtils.FormatType.SIMPLE_WITHOUT_SEPARATOR);
                if (DateUtil.compare(parse, currentDate) > 0) {
                    return HouseholdCountDto.SegmentEnum.UNKNOWN.getType();
                }
                int y = (int) DateUtil.betweenYear(parse, currentDate, Boolean.TRUE);
                int index = Arrays.binarySearch(segmentArr, y);
                return (byte) (index >= 0 ? index + 1 : -index);
            } catch (Exception e) {
                logger.error("解析身份证出错", e);
            }
            return HouseholdCountDto.SegmentEnum.UNKNOWN.getType();
        }, Collectors.collectingAndThen(Collectors.counting(), Long::intValue)));

        // 未统计到的年龄段，默认人数为0
        cMap.merge(HouseholdCountDto.SegmentEnum.UNKNOWN.getType(), 0, Integer::sum);
        cMap.merge(HouseholdCountDto.SegmentEnum.SEGMENT_1.getType(), 0, Integer::sum);
        cMap.merge(HouseholdCountDto.SegmentEnum.SEGMENT_2.getType(), 0, Integer::sum);
        cMap.merge(HouseholdCountDto.SegmentEnum.SEGMENT_3.getType(), 0, Integer::sum);
        cMap.merge(HouseholdCountDto.SegmentEnum.SEGMENT_4.getType(), 0, Integer::sum);
        cMap.merge(HouseholdCountDto.SegmentEnum.SEGMENT_5.getType(), 0, Integer::sum);
        cMap.merge(HouseholdCountDto.SegmentEnum.SEGMENT_6.getType(), 0, Integer::sum);

        // 组装数据成 list
        final int total = householdDtos.size();
        BigDecimal tb = new BigDecimal(String.valueOf(total));

        List<HouseholdCountDto.AgeSegmentCls> collect = cMap.entrySet().stream().map(o -> {
            HouseholdCountDto.AgeSegmentCls ageSegmentCls = new HouseholdCountDto.AgeSegmentCls();
            ageSegmentCls.setSegmentType(o.getKey());
            ageSegmentCls.setSegmentDesc(HouseholdCountDto.SegmentEnum.getDescByCode(o.getKey()));
            ageSegmentCls.setCount(o.getValue());
            String ratio = new BigDecimal(String.valueOf(o.getValue() * 100))
                    .divide(tb, 2, RoundingMode.HALF_UP).toPlainString();
            ageSegmentCls.setRatio(ratio + "%");
            return ageSegmentCls;
        }).sorted(Comparator.comparingInt(HouseholdCountDto.AgeSegmentCls::getSegmentType))
                .collect(Collectors.toList());

        householdCountDto.setAgeSegments(collect);

        return Response.<HouseholdCountDto>ok().wrap(householdCountDto);
    }

    @GetMapping("countDevice")
    @Operation(summary = "设备信息统计")
    public Response<DeviceCountDto> countDevice(
            @Parameter(description = "小区id 非必填") @RequestParam(required = false) Long villageId
    ) {
        Map<String, Object> params = Request.parseParams(httpServletRequest);
        super.fillAuthorityData(params);
        return Response.<DeviceCountDto>ok().wrap(deviceService.countDevice(params));
    }

    @GetMapping("countWorkOrder")
    @Operation(summary = "工单信息统计")
    public Response<WorkOrderCountDto> countWorkOrder(
            @Parameter(description = "小区id 非必填") @RequestParam(required = false) Long villageId
    ) {
        Map<String, Object> params = Request.parseParams(httpServletRequest);
        super.fillAuthorityData(params);

        return Response.<WorkOrderCountDto>ok().wrap(workOrderService.countWorkOrder(params));
    }

}
